export const flatToTree = (flatArray, treeOptions) => {
  const options = {
    id: 'id',
    parentId: 'parentId',
    children: 'children',
    ...treeOptions,
  }
  const dictionary = {} // a hash table mapping to the specific array objects with their ids as key
  const tree = []
  const children = options.children
  flatArray.forEach(node => {
    const nodeId = node[options.id]
    const nodeParentId = node[options.parentId]
    // set up current node data in dictionary
    dictionary[nodeId] = {
      [children]: null, // init a children property
      ...node, // add other propertys
      ...dictionary[nodeId], // children will be replaced if this node already has children property which was set below
    }
    dictionary[nodeParentId] = dictionary[nodeParentId] || { [children]: [] } // if it's not exist in dictionary, init an object with children property
    if (dictionary[nodeParentId][children] === null) { dictionary[nodeParentId][children] = [] }
    dictionary[nodeParentId][children].push(dictionary[nodeId]) // add reference to current node object in parent node object
  })
  // find root nodes
  Object.values(dictionary).forEach(obj => {
    if (typeof obj[options.id] === 'undefined') {
      tree.push(...obj[children])
    }
  })
  return tree
}

